查看原文
其他

FlutterComponent最佳实践之取色我来实现

徐宜生 群英传 2022-12-21

点击上方蓝字关注我,知识会给你力量


构建个性化的UI是非常酷的。你的应用程序不需要对每个人都是一样的。一个轻松定制你的应用程序的方法是,从客户资料/封面照片中提取调色板。

它是这样做的。

首先,我们从一个网址上加载图片到byte list中。

imageBytes = (await NetworkAssetBundle(Uri.parse(photo)).load(photo))
      .buffer
      .asUint8List();

然后,我们导入Image lib,这样我们就可以访问每个像素,而不用担心图像的格式问题。

在下面的方法中,我访问了一个像素mesh,所以我可以从图像的不同部分挑选颜色。

List<Color> extractPixelsColors(Uint8List? bytes) {
  List<Color> colors = [];

  List<int> values = bytes!.buffer.asUint8List();
  imageLib.Image? image = imageLib.decodeImage(values);

  List<int?> pixels = [];

  int? width = image?.width;
  int? height = image?.height;

  int xChunk = width! ~/ (noOfPixelsPerAxis + 1);
  int yChunk = height! ~/ (noOfPixelsPerAxis + 1);

  for (int j = 1; j < noOfPixelsPerAxis + 1; j++) {
    for (int i = 1; i < noOfPixelsPerAxis + 1; i++) {
      int? pixel = image?.getPixel(xChunk * i, yChunk * j);
      pixels.add(pixel);
      colors.add(abgrToColor(pixel!));
    }
  }

  return colors;
}

如果noOfPixelsPerAxis是4的话,这个网格看起来就是这样。

img

在这个例子中,我们将提取16个像素。

好了,现在我们有16种颜色,但我们能用它们做什么呢?我们需要以某种方式对它们进行排序,所以我们可以提取调色板。

img

现在我们尝试将颜色从浅色到深色排序。我们使用computeLuminance方法,这个方法的计算成本很高,所以我们也许不应该在排序方法中进行计算(对每种颜色进行多次计算),但为了这个例子,这也是可以的。

List<Color> sortColors(List<Color> colors) {
  List<Color> sorted = [];

  sorted.addAll(colors);
  sorted.sort((a, b) => b.computeLuminance().compareTo(a.computeLuminance()));

  return sorted;
}

经过分类,我们的颜色看起来像这样。

img

开始时图像较亮(左上方,结束时图像较暗,右下方)。我把它们显示在一个网格中,所以它们可以很容易地放在屏幕上。

我们不需要调色板中的所有16种颜色,这太多了,所以让我们试着提取4种颜色。

为了做到这一点,我将把这个16种颜色的列表分成4个4种颜色的子列表,在每个子列表中找到平均颜色,这些平均颜色将成为我们最终调色板颜色列表中的项目。

Color getAverageColor(List<Color> colors) {
  int r = 0, g = 0, b = 0;

  for (int i = 0; i < colors.length; i++) {
    r += colors[i].red;
    g += colors[i].green;
    b += colors[i].blue;
  }

  r = r ~/ colors.length;
  g = g ~/ colors.length;
  b = b ~/ colors.length;

  return Color.fromRGBO(r, g, b, 1);
}

平均颜色的计算方法是将所有的红色、蓝色和绿色成分加在一起,然后将总和除以所加颜色的数量。

img

调色板中的第一种颜色(右边没有1)是由排序列表中的前4种颜色(0、1、2、3)组成的,第二种颜色是4、5、6、7,第三种颜色是8、9、10、11,第四种是12、13、14、15。

为了防止用户界面被这些繁重的计算所阻塞,我使用了compute方法,它在一个独立的isolate(具有独立内存的新线程)上执行你的函数,并返回你的结果。

你从图像中提取的像素越多,就会花费更多的时间,所以要找到你要提取的最佳像素数。另外,图像越大,下载和解码的时间就越长。如果你能使用一些缩略图或你知道不是很大的图片,那将是最好的 :) 在下面的视频中,我提取了12x12=144像素,你可以看到它需要一两秒钟。

gif太大 看不了,请点击原文链接查看

原文链接:https://mobileappcircular.com/how-to-extract-a-color-palette-from-an-image-in-flutter-dart-d3d49699a5eb

源码地址:https://github.com/jelenalecic/coloring

向大家推荐下我的网站 https://xuyisheng.top/  点击原文一键直达

专注 Android-Kotlin-Flutter 欢迎大家访问



往期推荐


本文原创公众号:群英传,授权转载请联系微信(Tomcat_xu),授权后,请在原创发表24小时后转载。
< END >
作者:徐宜生

更文不易,点个“三连”支持一下👇


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存